package com.icee.myth.manager.channelHandler;

import com.icee.myth.common.protobufMessage.ProtobufMessageType;
import com.icee.myth.manager.Manager;
import com.icee.myth.manager.ServerMessageQueue;
import com.icee.myth.manager.config.ServerConfig;
import com.icee.myth.manager.db.DbHandler;
import com.icee.myth.manager.message.serverMessage.builder.ManagerMessageBuilder;
import com.icee.myth.protobuf.ConsoleToManagerProtocol.C2MGmProto;
import com.icee.myth.protobuf.ExternalCommonProtocol.IntValueProto;
import com.icee.myth.protobuf.ExternalCommonProtocol.LongValueProto;
import com.icee.myth.utils.LogConsts;
import com.icee.myth.utils.MLogger;
import com.icee.myth.utils.StackTraceUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.IOException;

/**
 * 服务器间通信，Console服务器发消息给Manager服务器的Handler
 *
 * @author liuxianke
 */
public class ConsoleToManagerHandler extends ChannelInboundHandlerAdapter { //SimpleChannelUpstreamHandler {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        // Add Deamon channel connected message to message queue
        ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildConsoleConnectMessage(ctx.channel()));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        // Add Deamon channel close message to message queue
        ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildConsoleCloseMessage(ctx.channel()));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 接收到从Deamon来的消息
        try {
            // Add Map channel received message to message queue
            ByteBuf buf = (ByteBuf) msg;
            short type = buf.readShort();
            short length = buf.readShort();
//            byte[] data = new byte[length];
//            buf.readBytes(data, 0, length);
//            buf = null;

            switch (type) {
                case ProtobufMessageType.CONSOLE2MANAGER_RUN_SERVER: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildRunServerMessage(intValue.getValue(), true));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_SHUTDOWN_SERVER: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildShutdownServerMessage(intValue.getValue()));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_DEBUG_RUN_SERVER: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildRunServerMessage(intValue.getValue(), false));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_SYNCCONFIG: {
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildSyncConfigMessage());
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_GET_SERVER_STATUS: {
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildGetServerStatusMessage());
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_GM: {
                    C2MGmProto gmProto = C2MGmProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    C2MGmProto gmProto = C2MGmProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildGmMessage(gmProto));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_CLEAR_TEST_FLAG: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildClearTestFlagMessage(intValue.getValue()));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_SET_TEST_FLAG: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildSetTestFlagMessage(intValue.getValue()));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_FORCE_SET_SERVER_SHUTDOWN_STATUS: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildForceSetServerShutdownStatusMessage(intValue.getValue()));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_LOAD_SERVER_CONFIG: {
                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    IntValueProto intValue = IntValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();

                    // 从数据库获取指定的服务器配置
                    DbHandler dbHandler = new DbHandler(Manager.INSTANCE.dbHost, Manager.INSTANCE.dbName);
                    ServerConfig serverConfig = dbHandler.getServerConfig(intValue.getValue());
                    dbHandler.close();

                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildLoadServerConfigMessage(intValue.getValue(), serverConfig));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_SET_SYSTEM_DATE: {
                    LongValueProto longValue = LongValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    LongValueProto longValue = LongValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();

                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildSetDateMessage(longValue.getValue()));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_SET_SYSTEM_TIME: {
                    LongValueProto longValue = LongValueProto.getDefaultInstance().newBuilderForType().mergeFrom(new ByteBufInputStream(buf)).build();
//                    LongValueProto longValue = LongValueProto.getDefaultInstance().newBuilderForType().mergeFrom(data).build();

                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildSetTimeMessage(longValue.getValue()));
                    break;
                }
                case ProtobufMessageType.CONSOLE2MANAGER_GET_SYSTEM_DATETIME: {
                    ServerMessageQueue.queue().offer(ManagerMessageBuilder.buildGetDateTimeMessage());
                    break;
                }
                default:
                    System.out.println("unknow case");
                    break;
            }
        } catch (IOException ex) {
            MLogger.getlogger().log(LogConsts.LOGTYPE_NETERR, StackTraceUtil.getStackTrace(ex));
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        MLogger.getlogger().debuglog(LogConsts.LOGLEVEL_DEBUG, StackTraceUtil.getStackTrace(cause));
        ctx.channel().close();
    }
}
